﻿//Copyright (c) Microsoft Corporation.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Linq;

namespace Microsoft.Ted.Wacel.TableStorage
{
    public class TableStorageDataProvider<T>: Base.IDataProvider
    {
        CloudTableStorage<TableItem<T>> mTable;

        private TableStorageConfiguration mConfiguration;
        string mConnectionString;
        string mName;
        string mPartitionField;
        string mRowField;

        public TableStorageDataProvider(string connectionString, string name, string partitionField = "Key", string rowField="Key")
        {
            mConnectionString = connectionString;
            mName = name;
            mPartitionField = partitionField;
            mRowField = rowField;
            mTable = new CloudTableStorage<TableItem<T>>(partitionField, rowField, connectionString, name, false);
        }

        public void Put(string key, object value, string partition = null)
        {
            mTable.InsertOrReplace(new TableItem<T> { Partition = (partition == null ? key : partition), Key = key, Value = (T)value });
        }
   
        public void Update(string key, object value, string partition = null )
        {
            mTable.Replace(new TableItem<T> { Partition = (partition == null ? key : partition), Key = key, Value = (T)value });
        }

        public object Get(string key, string partition = null, Type typeHint = null, Type typeHint2 = null)
        {
            var ret = mTable.Read(key, partitionId:(partition == null ? key : partition));
            if (ret == null)
                return null;
            else
                return ret.Value;
        }

        public void BulkPut(IEnumerable<KeyValuePair<string, object>> values, string partition = null)
        {
            mTable.BulkInsertOrReplace(
                from v in values
                select new TableItem<T> { Partition = (partition == null ? v.Key : partition), Key = v.Key, Value = (T)v.Value }
                );
        }
        public IEnumerable<KeyValuePair<string,object>> GetAll(string partition = null, Type typeHint = null, Type tpyeHint2 = null)
        {
            var items = mTable.List(partitionId:partition);
            List<KeyValuePair<string, object>> ret = new List<KeyValuePair<string, object>>();
            foreach (var item in items)
                ret.Add(new KeyValuePair<string, object>(item.Key, item.Value));
            return ret;
        }
        public IEnumerable<KeyValuePair<string, object>> BulkGet(List<string> keys, string partition = null, Type typeHint = null, Type typeHint2 = null)
        {
            var items= mTable.List((t) => keys.IndexOf(t.Key) >= 0, partitionId: partition);
            List<KeyValuePair<string, object>> ret = new List<KeyValuePair<string, object>>();
            foreach (var item in items)
                ret.Add(new KeyValuePair<string,object>(item.Key, item.Value));
            return ret;
        }
        public void Clear()
        {
            mTable.Clear();
        }

        public void Delete(string key, string partition = null)
        {
            mTable.Delete(key, partitionId: (partition == null? key: partition));
        }

        public Base.DataProviderConfiguration Configuration
        {
            get
            {
                return mConfiguration;
            }
            set
            {
                if (value is TableStorageConfiguration)
                    mConfiguration = (TableStorageConfiguration)value;
                else
                    throw new ArgumentException("Configuration is not a TableStorageConfiguration type");
                //TODO: react on configuration changes
            }
        }
        public Base.IDataProvider Clone(string newName)
        {
            return new TableStorageDataProvider<T>(mConnectionString, newName, mPartitionField, mRowField){ Configuration = (TableStorageConfiguration)mConfiguration.Clone() };
        }
    }
}
